package com.chungkui.check.core;

import com.chungkui.check.annotation.Check;
import com.chungkui.check.configparser.ParsingUtil;
import com.chungkui.check.configparser.RulesParser;
import com.chungkui.check.configparser.bean.CheckConfig;
import com.chungkui.check.expression.CheckConfigStore;
import com.chungkui.ratelimiter.RateLimiterCache;
import com.chungkui.check.util.JsonUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * @Author: jason
 * @Date: 2019/12/31 17:11
 * @Version 1.0
 */
public class CheckConfigStoreImpl implements CheckConfigStore {

    private Cache<String, CheckConfig> configCache;

    @Autowired
    private RateLimiterCache rateLimiterCache;

    @Autowired
    RulesParser rulesParser;
    private int capacity = 10;
    private int maximumSize = 10000;
    private boolean alwaysLoadRemote = false;

    public void setAlwaysLoadRemote(boolean alwaysLoadRemote) {
        this.alwaysLoadRemote = alwaysLoadRemote;
    }

    public CheckConfigStoreImpl(boolean alwaysLoadRemote) {
        this.alwaysLoadRemote = alwaysLoadRemote;
    }

    @Override
    public void remoteSetCallBack(String remote, String val) {
        CheckConfig checkConfig = configCache.getIfPresent(remote);
        if (checkConfig == null) {
            /*该校验未执行过不做处理*/
            return;
        }
        Map<String, Object> remoteConfig = JsonUtil.json2map(val);
        rulesParser.parsing(checkConfig, null, null, MapUtils.getObject(remoteConfig, "rules"));
        ParsingUtil.packageReSubmitWallConfig(checkConfig, null, MapUtils.getString(remoteConfig, "reSubmitWall"));
        ParsingUtil.parseDemoteConfig(checkConfig, MapUtils.getString(remoteConfig, "demote"));
        ParsingUtil.packageTrafficControlConfig(checkConfig, null, MapUtils.getString(remoteConfig, "trafficControl"));
        ParsingUtil.packageRateLimter(checkConfig, null, MapUtils.getString(remoteConfig, "rateLimters"));
        ParsingUtil.packageRedisRateLimter(checkConfig, null, MapUtils.getString(remoteConfig, "redisRateLimters"));
        ParsingUtil.packageCondition(checkConfig, null, MapUtils.getString(remoteConfig, "condition"));
        configCache.put(remote, checkConfig);
    }

    @Override
    public void clear() {
        configCache.invalidateAll();
        rateLimiterCache.clear();
    }

    protected CheckConfigStoreImpl() {
        initCache();
    }

    private void initCache() {
        configCache = CacheBuilder.newBuilder()
                .initialCapacity(capacity)
                .maximumSize(maximumSize)
                .build();
    }

    @PostConstruct
    public void init() {
        if (configCache == null) {
            initCache();
        }
    }

    public int getCapacity() {
        return capacity;
    }

    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }

    public int getMaximumSize() {
        return maximumSize;
    }

    public void setMaximumSize(int maximumSize) {
        this.maximumSize = maximumSize;
    }

    @Override
    public CheckConfig get(String key) {
        return configCache.getIfPresent(key);
    }

    @Override
    public CheckConfig parseCheckConfig(Check check, String key) {
        CheckConfig checkConfig = new CheckConfig();
        String remoteKey = check.remote();

        Map<String, Object> remoteConfig = null;
        if (StringUtils.isNotEmpty(remoteKey) || alwaysLoadRemote) {
            String remote = remoteGet(StringUtils.isNotEmpty(remoteKey) ? remoteKey : key, null);
            if (StringUtils.isNotEmpty(remote)) {
                remoteConfig = JsonUtil.json2map(remote);
            }
        }
        checkConfig.setKey(key);
        checkConfig.setMsgTmp(check.msgTemp());
        /*自定义参数校验*/
        rulesParser.parsing(checkConfig, check.value(), check.rules(), MapUtils.getObject(remoteConfig, "rules"));
        ParsingUtil.packageReSubmitWallConfig(checkConfig, check.reSubmitWall(), MapUtils.getString(remoteConfig, "reSubmitWall"));
        ParsingUtil.parseDemoteConfig(checkConfig, MapUtils.getString(remoteConfig, "demote"));
        ParsingUtil.packageTrafficControlConfig(checkConfig, check.trafficControl(), MapUtils.getString(remoteConfig, "trafficControl"));
        ParsingUtil.packageRateLimter(checkConfig, check.rateLimters(), MapUtils.getObject(remoteConfig, "rateLimters"));
        ParsingUtil.packageRedisRateLimter(checkConfig, check.redisRateLimters(), MapUtils.getObject(remoteConfig, "redisRateLimters"));
        ParsingUtil.packageCondition(checkConfig, check.condition(), MapUtils.getString(remoteConfig, "condition"));
        configCache.put(key, checkConfig);
        return checkConfig;
    }

    @Override
    public String remoteGet(String key, String defaultValue) {
        return null;
    }


}
